package com.glodon.paas.document.biz.impl;

import java.util.Date;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.glodon.paas.document.biz.RevisionBiz;
import com.glodon.paas.document.constant.DocumentConstant;
import com.glodon.paas.document.dao.FileDao;
import com.glodon.paas.document.dao.MultiPartUploadHandleDao;
import com.glodon.paas.document.dao.PartDao;
import com.glodon.paas.document.dao.PublicTokenDao;
import com.glodon.paas.document.dao.RevisionDao;
import com.glodon.paas.document.dao.domain.FileInfoEntity;
import com.glodon.paas.document.dao.domain.MultiPartUploadHandleEntity;
import com.glodon.paas.document.dao.domain.PartEntity;
import com.glodon.paas.document.dao.domain.PublicTokenEntity;
import com.glodon.paas.document.dao.domain.RevisionEntity;
import com.glodon.paas.document.service.util.WebService;
import com.glodon.paas.exception.PaasServerExceptionFactory;
import com.glodon.paas.exception.StorageException;
import com.glodon.paas.storage.BulkStorage;
import com.glodon.paas.util.UUIDUtil;

@Repository("revisionBiz")
public class RevisionBizImpl implements RevisionBiz {

    private static final Logger      LOGGER = LoggerFactory.getLogger(RevisionBizImpl.class);

    @Autowired
    private FileDao                  fileDao;
    @Autowired
    private RevisionDao              revisionDao;

    @Autowired
    private MultiPartUploadHandleDao handleDao;

    @Autowired
    private PartDao                  partDao;

    @Autowired
    private BulkStorage              bulkStorage;
    
    @Autowired
//    private PublicTokenDao publicTokenDao;

    @Override
    public BulkStorage getBulkStorage() {
        return bulkStorage;
    }

    @Override
    public void setBulkStorage(BulkStorage bulkStorage) {
        this.bulkStorage = bulkStorage;
    }

    @Override
    public void insertRevision(RevisionEntity revisionEntity) {
        if (revisionEntity == null) {
            throw PaasServerExceptionFactory.validateException("Revision is empty, can not update it.", null);
        }
        if (StringUtils.isEmpty(revisionEntity.getId())) {
            revisionEntity.setId(UUIDUtil.getUUIDStr());
        }
        revisionDao.insert(revisionEntity);
        // if(StringUtils.isNotEmpty(revisionEntity.getStorageKey())){
        // fileDao.updateSizeRevisionNum(revisionEntity.getFileId(), revisionEntity.getRevisionNumber(),
        // revisionEntity.getFileSize());
        // fileDao.increaseCount(revisionEntity.getFileId());
        // }
    }

    @Override
    public List<RevisionEntity> getRevisions(String fileId) {
        List<RevisionEntity> revisions = revisionDao.getRevisionsByFile(fileId);
        // for(int index=0;index<revisions.size();index++){
        // if(StringUtils.isEmpty(revisions.get(index).getStorageKey())){
        // revisions.remove(index);
        // }
        // }
        return revisions;
    }

    @Override
    public List<RevisionEntity> getAllRevisions(String fileId) {
        return revisionDao.getRevisionsByFile(fileId);
    }

    @Override
    public MultiPartUploadHandleEntity getHandlerByRevision(String revisionId) {
        return handleDao.getHandlerByRevision(revisionId);
    }

    @Override
    public RevisionEntity getUploadingRevision(String fileId) {
        if (StringUtils.isEmpty(fileId)) {
            throw PaasServerExceptionFactory.validateException("fileId is empty.", null);
        }
        return revisionDao.getLatestUnavailableRevision(fileId);
    }

    // @Override
    // public RevisionEntity getLatestAvailableRevision(String fileId) {
    // if(StringUtils.isEmpty(fileId)){
    // throw PaasServerExceptionFactory.validateException("fileId is empty.", null);
    // }
    // return revisionDao.getLatestAvailableRevision(fileId);
    // }

    @Override
    public PartEntity getLatestPartByRevision(String revisionId) {
        if (StringUtils.isEmpty(revisionId)) {
            throw PaasServerExceptionFactory.validateException("revisionId is empty.", null);
        }

        return partDao.getLatestPartByRevision(revisionId);
    }

    @Override
    public void insertPart(PartEntity part) {
        if (part == null) {
            throw PaasServerExceptionFactory.validateException("part is empty.", null);
        }
        if (StringUtils.isEmpty(part.getId())) {
            part.setId(UUIDUtil.getUUIDStr());
        }
        partDao.insert(part);
    }

    @Override
    public void delParts(String revisionId) {
        if (StringUtils.isEmpty(revisionId)) {
            throw PaasServerExceptionFactory.validateException("revisionId is empty.", null);
        }
        partDao.delParts(revisionId);
    }

    @Override
    public List<PartEntity> getPartsByRevision(String revisionId) {
        if (StringUtils.isEmpty(revisionId)) {
            throw PaasServerExceptionFactory.validateException("revisionId is empty.", null);
        }

        return partDao.getPartsByRevision(revisionId);
    }

    @Override
    public int getPartsCountByRevision(String revisionId) {
        if (StringUtils.isEmpty(revisionId)) {
            throw PaasServerExceptionFactory.validateException("revisionId is empty.", null);
        }

        return partDao.getPartsCountByRevision(revisionId);
    }

    @Override
    public void insertHandler(MultiPartUploadHandleEntity handler) {
        if (handler == null) {
            throw PaasServerExceptionFactory.validateException("handler is empty.", null);
        }
        if (StringUtils.isEmpty(handler.getRevisionId())) {
            throw PaasServerExceptionFactory.validateException("revisionId is empty.", null);
        }
        handleDao.insert(handler);
    }

    @Override
    public void delHandler(String revisionId) {
        if (revisionId == null) {
            throw PaasServerExceptionFactory.validateException("revisionId is empty.", null);
        }
        handleDao.delete(revisionId);
    }

    // @Override
    // public RevisionEntity getLatestAvailableRevision(String fileId) {
    // if(fileId == null){
    // throw PaasServerExceptionFactory.validateException("fileId is empty.", null);
    // }
    // return revisionDao.getLatestAvailableRevision(fileId);
    // }

    @Override
    public RevisionEntity getRevision(String fileId, int revisionNum) {
        if (fileId == null) {
            throw PaasServerExceptionFactory.validateException("fileId is empty.", null);
        }
        if (revisionNum <= 0) {
            throw PaasServerExceptionFactory.validateException("revisionNum is incorrect, value is " + revisionNum
                                                               + ".", null);
        }
        return revisionDao.getRevision(fileId, revisionNum);
    }

    @Override
    public void updateRevision(RevisionEntity revision) {
        if (revision == null) {
            throw PaasServerExceptionFactory.validateException("Revision is empty, can not update it.", null);
        }
        revisionDao.updateRevision(revision);
    }

    @Override
    public RevisionEntity getRevision(String revisionId) {
        if (StringUtils.isEmpty(revisionId)) {
            throw PaasServerExceptionFactory.validateException("RevisionId is empty.", null);
        }
        return revisionDao.get(revisionId);
    }

    @Override
    public void updateDataBagId(RevisionEntity revision, String dataBagId) {
        fileDao.updateDataBagId(revision.getFileId(), dataBagId);
        revisionDao.updateDataBagId(revision.getId(), dataBagId);
    }

    @Override
    public void deleteRevision(RevisionEntity r) {
        if (r == null) {
            return;
        }
        deleteContent(r);
        if (StringUtils.isEmpty(r.getStorageKey())) {
            delHandler(r.getId());
            delParts(r.getId());
        }
        revisionDao.delete(r.getId());
    }

    private void deleteContent(RevisionEntity r) {
        try {
            if (StringUtils.isNotEmpty(r.getStorageKey())) {
                bulkStorage.delete(r.getStorageKey());
                LOGGER.debug("delete file content, key:" + r.getStorageKey());
            } else {
                MultiPartUploadHandleEntity handler = this.getHandlerByRevision(r.getId());
                if (handler != null) {
                    bulkStorage.abortMultiPartUpload(MultiPartUploadHandleEntity.getDto(handler));
                    LOGGER.debug("abort file content, key:" + handler.getKey());
                }
            }
        } catch (StorageException se) {
            LOGGER.error(se.getMessage(), se);
        }
    }

    @Override
    public void activeRevision(RevisionEntity revision) {
        revision.setTimestamp(new Date());
        if (revisionDao.get(revision.getId()) == null) {
            revisionDao.insert(revision);
        } else {
            revisionDao.updateRevision(revision);
            partDao.delParts(revision.getId());
            handleDao.delete(revision.getId());
        }
        int count = fileDao.get(revision.getFileId()).getCount();
        fileDao.updateSizeNumCount(revision.getFileId(), revision.getFileSize(), revision.getRevisionNumber(),
                                   count + 1, revision.getTimestamp());
    }

    @Override
    public void refreshFile(FileInfoEntity file) {
        List<RevisionEntity> rs = this.getRevisions(file.getId());
        // Integer count = rs.size();
        Long size = 0L;
        Integer num = -1;
        String dataBagId = null;
        Date updateTime = null;
        for (RevisionEntity r : rs) {
            if (StringUtils.isBlank(r.getStorageKey())) {
                rs.remove(r);
            } else if (num < r.getRevisionNumber()) {
                num = r.getRevisionNumber();
                dataBagId = r.getDataBagId();
                size = r.getFileSize();
                updateTime = r.getTimestamp();
            }
        }
        if (num.intValue() == file.getActiveRevision().intValue()) {
            fileDao.updateCount(file.getId(), rs.size());
            file.setCount(rs.size());
        } else {
            fileDao.updateSizeNumCount(file.getId(), size, num, rs.size(), updateTime);
            fileDao.updateDataBagId(file.getId(), dataBagId);
            file.setSize(size);
            file.setActiveRevision(num);
            file.setUpdateTime(updateTime);
            file.setDataBagId(dataBagId);
        }
    }

    @Override
    public RevisionEntity getRevisionByDatabag(String databagId) {
        if (StringUtils.isBlank(databagId)) {
            throw PaasServerExceptionFactory.validateException("databagId is empty.", null);
        } else {
            return revisionDao.getRevisionByDatabag(databagId);
        }
    }
}
